package com.douding.server.service;

import com.douding.server.domain.*;
import com.douding.server.dto.*;
import com.douding.server.exception.ValidatorException;
import com.douding.server.mapper.*;
import com.douding.server.mapper.my.MyCourseMapper;
import com.douding.server.util.CopyUtil;
import com.douding.server.util.UuidUtil;
import com.douding.server.util.ValidatorUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;


/**
 * @author L
 */
@Service
public class CourseService {

    @Resource
    private CourseMapper courseMapper;

    @Resource
    private MyCourseMapper myCourseMapper;

    @Resource
    private CourseCategoryService myCategoryService;

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private CourseContentMapper courseContentMapper;

    @Resource
    private TeacherService teacherService;

    @Resource
    private ChapterService chapterService;

    @Resource
    private SectionService sectionService;

    @Resource
    private CourseCategoryMapper courseCategoryMapper;

    @Resource
    private CourseCategoryService courseCategoryService;

    @Resource
    private CourseContentFileMapper courseContentFileMapper;

    @Resource
    private MemberCourseMapper memberCourseMapper;

    @Resource
    private SectionMapper sectionMapper;


    private static final Logger LOG = LoggerFactory.getLogger(CourseService.class);


    /**
     * 列表查询：关联课程分类表 web接口
     *
     * @param pageDto
     */
    @Transactional(rollbackFor = Exception.class)
    public void list(CoursePageDto pageDto) {
        // 查询所有课程信息
        PageHelper.startPage(pageDto.getPage(), pageDto.getSize());
        CourseExample courseExample = new CourseExample();
        courseExample.setOrderByClause("sort asc");
        List<Course> courses = courseMapper.selectByExample(courseExample);
        // 开启异步任务进行更新
        new FutureTask<Void>(() -> {
            for (Course course : courses) {
                updateTime(course.getId());
            }
            return null;
        }).run();
        PageInfo<Course> pageInfo = new PageInfo<>(courses);
        pageDto.setTotal(pageInfo.getTotal());
        // 对于每个课程信息，封装其关联信息
        List<CourseDto> courseDtos = parse(courses);
        pageDto.setList(courseDtos);
    }

    /**
     * 封装课程相关信息
     *
     * @param courses courseDto
     * @return List<CourseDto></CourseDto>
     */
    private List<CourseDto> parse(List<Course> courses) {
        // 对于每个课程信息，封装其关联信息
        return courses.stream().map(this::computed).collect(Collectors.toList());
    }

    private CourseDto computed(Course course) {
        String courseId = course.getId();
        String teacherId = course.getTeacherId();
        // 获取内容
        CourseContent courseContent = courseContentMapper.selectByPrimaryKey(courseId);
        String content = "";
        if (!ObjectUtils.isEmpty(courseContent)) content = courseContent.getContent();
        // 获取教师信息
        TeacherDto teacherDto = teacherService.findById(teacherId);
        // 获取分类信息
        // 1.1 获取分类id列表
        List<String> categoryIds = myCategoryService.listByCourse(courseId)
                .stream()
                .map(CourseCategoryDto::getCategoryId)
                .collect(Collectors.toList());
        // 1.2 根据id列表查找course表
        CategoryExample example = new CategoryExample();
        example.createCriteria().andIdIn(categoryIds);
        List<Category> categories = categoryMapper.selectByExample(example);
        List<CategoryDto> categoryDtos = CopyUtil.copyList(categories, CategoryDto.class);
        // 获取章节信息
        List<ChapterDto> chapterDtos = chapterService.listByCourse(courseId);
        // 获取块
        List<SectionDto> sectionDtos = sectionService.listByCourse(courseId);
        // 合并
        CourseDto courseDto = CopyUtil.copy(course, CourseDto.class);
        courseDto.setChapters(chapterDtos);
        courseDto.setSections(sectionDtos);
        courseDto.setContent(content);
        courseDto.setTeacher(teacherDto);
        courseDto.setCategorys(categoryDtos);
        // 返回结果
        return courseDto;
    }


    @Transactional(rollbackFor = Exception.class)
    public void save(CourseDto courseDto) {
        preCheck(courseDto);
        String courseId = courseDto.getId();
        Course course = CopyUtil.copy(courseDto, Course.class);
        // 更新
        if (!StringUtils.isEmpty(courseId)) {
            // 修改课程相关信息
            update(course);
            // 修改course_id和category_id关联表
            List<CategoryDto> categorys = courseDto.getCategorys();
            if (!CollectionUtils.isEmpty(categorys)) {
                // 删除所有于course_id关联的数据
                CourseCategoryExample courseCategoryExample = new CourseCategoryExample();
                courseCategoryExample.createCriteria().andCourseIdEqualTo(courseId);
                courseCategoryMapper.deleteByExample(courseCategoryExample);
                // 添加
                courseCategoryService.saveBatch(courseId, categorys);
            }
            // 修改章节（由于表单并未涉及，故无需修改或删除）
            // 修改课程section（由于表单并未涉及，故无需修改或删除）
            return;
        }
        // 插入课程数据
        insert(course);
        // 先删除后添加course_id和category_id管理数据
        CourseCategoryExample courseCategoryExample = new CourseCategoryExample();
        courseCategoryExample.createCriteria().andCourseIdEqualTo(course.getId());
        courseCategoryMapper.deleteByExample(courseCategoryExample);
        courseCategoryService.saveBatch(course.getId(), courseDto.getCategorys());
    }

    private void preCheck(CourseDto courseDto) {
        assert !ObjectUtils.isEmpty(courseDto);
        ValidatorUtil.require(courseDto.getName(), "课程名称", String.class);
        ValidatorUtil.require(courseDto.getImage(), "封面", String.class);
        ValidatorUtil.require(courseDto.getPrice(), "价格", BigDecimal.class);
        ValidatorUtil.require(courseDto.getEnroll(), "报名数", Integer.class);
        ValidatorUtil.require(courseDto.getTeacherId(), "教师ID", String.class);
        if (CollectionUtils.isEmpty(courseDto.getCategorys())) {
            throw new ValidatorException("参数校验出错！");
        }
    }

    private void insert(Course course) {
        course.setCreatedAt(new Date());
        course.setId(UuidUtil.getShortUuid());
        courseMapper.insert(course);
    }

    //更新数据
    private void update(Course course) {
        CourseExample courseExample = new CourseExample();
        course.setUpdatedAt(new Date());
        courseExample.createCriteria().andIdEqualTo(course.getId());
        courseMapper.updateByExample(course, courseExample);
    }

    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        // 删除course_category中的数据
        CourseCategoryExample courseCategoryExample = new CourseCategoryExample();
        courseCategoryExample.createCriteria().andCourseIdEqualTo(id);
        courseCategoryMapper.deleteByExample(courseCategoryExample);
        // 删除course_content数据
        CourseContentExample courseContentExample = new CourseContentExample();
        courseContentExample.createCriteria().andIdEqualTo(id);
        courseContentMapper.deleteByExample(courseContentExample);
        // 删除course_content_file数据
        CourseContentFileExample courseContentFileExample = new CourseContentFileExample();
        courseCategoryExample.createCriteria().andCourseIdEqualTo(id);
        courseContentFileMapper.deleteByExample(courseContentFileExample);
        // 删除member_course数据
        MemberCourseExample memberCourseExample = new MemberCourseExample();
        memberCourseExample.createCriteria().andCourseIdEqualTo(id);
        memberCourseMapper.deleteByExample(memberCourseExample);
        // 删除section当中包含course_id的字段
        SectionExample sectionExample = new SectionExample();
        sectionExample.createCriteria().andCourseIdEqualTo(id);
        sectionMapper.deleteByExample(sectionExample);
        // 删除course中数据
        CourseExample courseExample = new CourseExample();
        courseExample.createCriteria().andIdEqualTo(id);
        courseMapper.deleteByExample(courseExample);
    }

    /**
     * 更新课程时长
     *
     * @param courseId
     */
    @Transactional
    public void updateTime(@Param("courseId") String courseId) {
        SectionExample example = new SectionExample();
        example.createCriteria().andCourseIdEqualTo(courseId);
        List<Section> sections = sectionMapper.selectByExample(example);
        // 记录当前课程下的所有视频的总描述
        Integer time = 0;
        if (!CollectionUtils.isEmpty(sections)) {
            for (Section section : sections) {
                if (!ObjectUtils.isEmpty(section.getTime()))
                    time += section.getTime();
            }
        }
        // 更新操作
        Course course = new Course();
        course.setTime(time);
        course.setId(courseId);
        update(course);
    }

    //课程内容相关的操作 查找 新增,修改
    public CourseContentDto findContent(String id) {
        CourseContent courseContent = courseContentMapper.selectByPrimaryKey(id);
        CourseContentDto courseContentDto = CopyUtil.copy(courseContent, CourseContentDto.class);
        return courseContentDto;
    }

    /**
     * 修改内容
     *
     * @param contentDto contentDto
     * @return int
     */
    public int saveContent(CourseContentDto contentDto) {
        ValidatorUtil.require(contentDto, "CourseContentDto类对象", CourseContentDto.class);
        ValidatorUtil.require(contentDto.getId(), "课程id", String.class);
        // 先进行更新
        CourseContentExample courseContentExample = new CourseContentExample();
        courseContentExample.createCriteria().andIdEqualTo(contentDto.getId());
        CourseContent courseContent = CopyUtil.copy(contentDto, CourseContent.class);
        int i = courseContentMapper.updateByExample(courseContent, courseContentExample);
        // 更新此时为0，表示数据未插入，进行insert即可
        if (i == 0) {
            i = courseContentMapper.insert(courseContent);
        }
        return i;
    }


    public void sort(SortDto sortDto) {
        CourseExample example = new CourseExample();
        example.createCriteria().andIdEqualTo(sortDto.getId());
        Course course = new Course();
        // 判断优先级是否发现改变
        if (sortDto.getOldSort() != sortDto.getNewSort()) {
            course.setSort(sortDto.getNewSort());
            courseMapper.updateByExample(course, example);
        }
    }

    /**
     * 查找某一课程，供web模块用，只能查已发布的
     *
     * @param id
     * @return
     */
    public CourseDto findCourse(String id) {
        CourseExample courseExample = new CourseExample();
        courseExample.setOrderByClause("sort desc");
        courseExample.createCriteria().andIdEqualTo(id).andStatusEqualTo("P");
        List<Course> courses = courseMapper.selectByExample(courseExample);
        CourseDto courseDto = null;
        if (!CollectionUtils.isEmpty(courses)) {
            courseDto = computed(courses.get(0));
        }
        return courseDto;
    }

    /**
     * 新课列表查询，只查询已发布的，按创建日期倒序
     */
    public List<CourseDto> listNew(PageDto pageDto) {
        PageHelper.startPage(pageDto.getPage(), pageDto.getSize());
        CourseExample courseExample = new CourseExample();
        courseExample.setOrderByClause("created_at desc");
        courseExample.createCriteria().andStatusEqualTo("P");
        List<Course> courses = courseMapper.selectByExample(courseExample);
        PageInfo<Course> pageInfo = new PageInfo<>(courses);
        pageDto.setTotal(pageInfo.getTotal());
        return CopyUtil.copyList(courses, CourseDto.class);
    }



}//end class
